import {Button, Col, Divider, Form, FormInstance, Input, Modal, Row, Select, Table} from "antd";
import './style/MainPage.css'
import React, {useEffect, useState} from "react";
import {useAppContext} from "../utils/Context";
import TextArea from "antd/es/input/TextArea";
import {CefQueryCfg} from "../message/CefQueryCfg";
import {CefKey} from "../message/CefKey.Const";
import {axiosCefQuery, sendCefQuery} from "../message/cefQueryHandler";
import {addSqlStatement, getSqlStatements, SqlStatementType} from "./SqlPage";
type QueryDataType = {
    dataList: TableData[];
    columnList: string[];
};
type TableData = {
    [key: string]: any;
}
type Columns = {
    key: string,
    dataIndex: string,
    title: string,
}
type QueryForm = {
    dataSourceId: number,
    sql: string
}
type AddSqlFormProps = {
    form: FormInstance,
    sql: string
}
export const SESSION_STORAGE_SEARCH_FORM = "profilerExQueryFormData";
export const SESSION_STORAGE_TABLE_COLUMN = "profilerExQueryTableColumn";
export const SESSION_STORAGE_TABLE_DATA = "profilerExQueryTableData";
export const MainPage: React.FC = () => {
    const {dataSources, setSqlStatements, messageApi} = useAppContext();
    const [tableData, setTableData] = useState<TableData[]>(initTableData);
    const [loading, setLoading] = useState(false);
    const [dataSourceId, setDataSourceId] = useState();
    const [columns, setColumns] = useState<Columns[]>(initColumn);
    const [openModal, setOpenModal] = useState(false);
    const [querySqlForm] = Form.useForm<QueryForm>();
    const [addSqlForm] = Form.useForm<SqlStatementType>();
    const sqlStatement = Form.useWatch('sql', querySqlForm);

    useEffect(() => {
        const url = window.URL;
        console.log(url);
        const data = sessionStorage.getItem(SESSION_STORAGE_SEARCH_FORM);
        if (data) {
            querySqlForm.setFieldsValue(JSON.parse(data));
        }
    }, [querySqlForm]);
    const saveCsv = () => {
        const cfg = new CefQueryCfg(CefKey.MAIN_QUERY);
        cfg.data = {
            method: 'saveAsCsv',
            params: {}
        }
        sendCefQuery(cfg);
    }

    const saveSql = async () => {
        const values = await addSqlForm.validateFields();
        addSqlStatement(values.name, values.sql, (response) => {
            getSqlStatements((response) => {
                setSqlStatements(JSON.parse(response).body as SqlStatementType[]);
            });
            messageApi.info("保存成功");
            setOpenModal(false);
            addSqlForm.resetFields();
        });
    }

    const searchData = (values: QueryForm) => {
        setLoading(true);
        const cfg = new CefQueryCfg(CefKey.MAIN_QUERY);
        cfg.data = {
            method: 'query',
            params: {
                sql: values.sql,
                dataSourceId: values.dataSourceId,
                dataSourcePath: dataSources.find(ds => ds.id === values.dataSourceId)?.path
            }
        }
        sendCefQuery(cfg, (response) => {
            setLoading(false);
            const queryDataType = JSON.parse(response).body as QueryDataType;
            setColumns(queryDataType.columnList.map((col)=>({
                title: col,
                dataIndex: col,
                key: col
            })));
            setTableData(queryDataType.dataList);
            sessionStorage.setItem(SESSION_STORAGE_TABLE_DATA, JSON.stringify(queryDataType.dataList));
        }, ()=>{
            setLoading(false);
        });
    };
    const queryFormValuesChange = (changedValues: any, values: QueryForm) => {
        sessionStorage.setItem(SESSION_STORAGE_SEARCH_FORM, JSON.stringify(values));
    }
    const queryFunctionData = async (values: QueryForm)=> {
        setLoading(true);
        const cfg = new CefQueryCfg(CefKey.MAIN_QUERY);
        cfg.data = {
            method: 'functionQuery',
            params: {
                sql: values.sql,
                dataSourceId: values.dataSourceId,
                dataSourcePath: dataSources.find(ds => ds.id === values.dataSourceId)?.path
            }
        }
        sendCefQuery(cfg, (response) => {
            setLoading(false);
            const queryDataType = JSON.parse(response).body as QueryDataType;
            setColumns(queryDataType.columnList.map((col)=>({
                title: col,
                dataIndex: col,
                key: col,
                sorter: (a: any, b: any)=>{
                    if (typeof a[col]==='string' && typeof b[col]==='string') {
                        return a[col].localeCompare(b[col]);
                    }
                    return a[col]-b[col];
                }
            })));
            setTableData(queryDataType.dataList);
            sessionStorage.setItem(SESSION_STORAGE_TABLE_DATA, JSON.stringify(queryDataType.dataList));
        }, ()=>{
            setLoading(false);
        });
    }
    return (
        <Form name="search" onFinish={searchData} form={querySqlForm} onValuesChange={queryFormValuesChange}>
            <Row gutter={[undefined, 20]} justify="center">
                <Col span={8}>
                    <Form.Item rules={[{required: true, message: "请选择数据源"}]} name="dataSourceId" label="数据源: ">
                        <Select showSearch placeholder="选择一个数据源" size="large"
                                value={dataSourceId}
                                onChange={(value) => setDataSourceId(value)}
                                options={dataSources.map(ds =>
                                    ({value: ds.id, label: ds.name, key: ds.id})
                                )}
                        >
                        </Select>
                    </Form.Item>
                </Col>
            </Row>
            <Row className="marginTopRow" gutter={[20, 20]} justify="center">
                <Col span={16}>
                    <Form.Item rules={[{required: true, message: '请输入sql语句'}]} name="sql">
                        <TextArea
                            placeholder="请输入sql语句"
                            autoSize={{minRows: 4, maxRows: 6}}
                        />
                    </Form.Item>
                </Col>
                <Col span={2}>
                    <Row gutter={[undefined, 25]}>
                        <Button className='searchButton' type="primary" htmlType="submit" loading={loading}>
                            查询
                        </Button>
                        <Button className='searchButton' onClick={async () => {
                            await querySqlForm.validateFields(["sql"]).then(() => setOpenModal(true)).catch(() => {
                            });
                        }}>
                            保存sql
                        </Button>
                        <Modal
                            title="新增sql语句"
                            open={openModal}
                            onOk={() => saveSql()}
                            // confirmLoading={confirmLoading}
                            onCancel={() => {
                                setOpenModal(false);
                                addSqlForm.resetFields();
                            }}
                        >
                            <AddSqlStatementForm form={addSqlForm} sql={sqlStatement}/>
                        </Modal>
                    </Row>

                </Col>
                <Col span={20}>
                    <Button className='searchButton' type="primary" style={{width:"auto"}} loading={loading}
                            onClick={async () => queryFunctionData(await querySqlForm.validateFields())}  size="large">
                        查询function耗时
                    </Button>
                </Col>
                <Divider/>
                <Col span={20}>
                    <Row justify='end'>
                        <Button onClick={saveCsv}>
                            保存为csv
                        </Button>
                    </Row>
                </Col>
                <Col span={24}>
                    <Table columns={columns} dataSource={tableData}></Table>
                </Col>
            </Row>
        </Form>

    );
}

const AddSqlStatementForm: React.FC<AddSqlFormProps> = (props: AddSqlFormProps) => {
    return (
        <Form form={props.form}>
            <Form.Item<SqlStatementType>
                label="名称"
                name="name"
                rules={[{required: true, message: '输入名称'}]}
            >
                <Input/>
            </Form.Item>
            <Form.Item<SqlStatementType>
                label="sql语句"
                name="sql"
                initialValue={props.sql}
                rules={[{required: true, message: '输入sql语句'}]}
            >
                <TextArea disabled/>
            </Form.Item>
        </Form>
    );
}

const initColumn = () => {
    const column = sessionStorage.getItem(SESSION_STORAGE_TABLE_COLUMN);
    if (column) {
        return JSON.parse(column);
    }
    return [];
}
const initTableData = () => {
    const tableData = sessionStorage.getItem(SESSION_STORAGE_TABLE_DATA);
    if (tableData) {
        return JSON.parse(tableData);
    }
    return [];
}